package com.ojoin.trade.common.utils;

import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ojoin.trade.common.Constants;
import com.ojoin.trade.common.utils.json.JSONUtils;
import com.ojoin.trade.common.web.shiro.Principal;

public class LogUtils {

    public static final Logger ACCESS_LOG = LoggerFactory.getLogger("access");
    public static final Logger T0LOAN_LOG = LoggerFactory.getLogger("t0loan");
    public static final Logger SLLOAN_LOG = LoggerFactory.getLogger("slloan");
    
    /**
     * 记录访问日志
     * [username][jsessionid][ip][accept][UserAgent][url][params][Referer]
     *
     * @param request
     */
    public static void logAccess(HttpServletRequest request) {
        String username = getUsername();
        String jsessionId = request.getRequestedSessionId();
        String ip = IpUtils.getIpAddr(request);
        String accept = request.getHeader("accept");
        String userAgent = request.getHeader("User-Agent");
        String url = request.getRequestURI();
        String params = getParams(request);
        String headers = getHeaders(request);

        StringBuilder s = new StringBuilder();
        s.append(getBlock(username));
        s.append(getBlock(jsessionId));
        s.append(getBlock(ip));
        s.append(getBlock(accept));
        s.append(getBlock(userAgent));
        s.append(getBlock(request.getMethod()));//tag Head Nginx check
        s.append(getBlock(url));
        s.append(getBlock(params));
        s.append(getBlock(headers));
        s.append(getBlock(request.getHeader("Referer")));
        getAccessLog().info(s.toString());
    }
    
    /**
     * info 无格式参数
     * @param log
     * @param message
     */
	public static void info(Logger log,String message) {
		StringBuilder s = new StringBuilder();
		s.append(getBlock(getLineInfo()));
		s.append(getBlock(getUsername()));
        s.append(getBlock(message));
        log.info(s.toString());
	}
	
	/**
	 * info 多参数
	 * @param log
	 * @param message
	 * @param param
	 */
	public static void info(Logger log,String message,Object... param ) {
		StringBuilder s = new StringBuilder();
		s.append(getBlock(getLineInfo()));
		s.append(getBlock(getUsername()));
        s.append(getBlock(String.format(message.replaceAll("\\{\\}","%s"), param)));
        log.info(s.toString());
	}

	/**
     * 记录异常错误
     * 格式 [exception]
     *
     * @param message
     * @param e
     */
    public static void error(Logger log, Throwable e,String message,Object... param) {
        StringBuilder s = new StringBuilder();
        s.append(getBlock(getLineInfo()));
        s.append(getBlock(getUsername()));
        s.append(getBlock("exception"));
        s.append(getBlock(String.format(message.replaceAll("\\{\\}","%s"), param)));
        Throwable root = ExceptionUtils.getRootCause(e);
		root = (root == null) ? e : root;
        log.error(s.toString(), root);
         
    }
    
    /**
     * 记录异常错误
     * 格式 [exception]
     *
     * @param message
     * @param e
     */
    public static void error(Logger log, Throwable e,String message) {
        StringBuilder s = new StringBuilder();
        s.append(getBlock(getLineInfo()));
        s.append(getBlock(getUsername()));
        s.append(getBlock("exception"));
        s.append(getBlock(message));
        Throwable root = ExceptionUtils.getRootCause(e);
		root = (root == null) ? e : root;
        log.error(s.toString(), root);
         
    }
    
    /**
     * 记录异常错误
     * 格式 [exception]
     *
     * @param log
     * @param e
     */
    public static void error(Logger log, Throwable e) {
        StringBuilder s = new StringBuilder();
        s.append(getBlock(getLineInfo()));
        s.append(getBlock(getUsername()));
        s.append(getBlock("exception"));
        s.append(getBlock(e.getMessage()));
        Throwable root = ExceptionUtils.getRootCause(e);
		root = (root == null) ? e : root;
        log.error(s.toString(), root);
    }
    
    /**
     * 记录异常错误
     * 格式 [exception]
     *
     * @param message
     */
    public static void error(Logger log,String message) {
        StringBuilder s = new StringBuilder();
        s.append(getBlock(getLineInfo()));
        s.append(getBlock(getUsername()));
        s.append(getBlock(message));
        log.error(s.toString());
    }

    public static String getBlock(Object msg) {
        if (msg == null) {
            msg = "";
        }
        return "[" + msg.toString() + "]";
    }


    protected static String getParams(HttpServletRequest request) {
        Map<String, String[]> params = request.getParameterMap();
        return JSONUtils.toJSONString(params);
    }


    private static String getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = Maps.newHashMap();
        Enumeration<String> namesEnumeration = request.getHeaderNames();
        while(namesEnumeration.hasMoreElements()) {	
            String name = namesEnumeration.nextElement();
            Enumeration<String> valueEnumeration = request.getHeaders(name);
            List<String> values = Lists.newArrayList();
            while(valueEnumeration.hasMoreElements()) {
                values.add(valueEnumeration.nextElement());
            }
            headers.put(name, values);
        }
        return JSONUtils.toJSONString(headers);
    }

    protected static String getUsername() {
    	Principal loginName=CommonUtils.getPrincipal();
    	String ret=Constants.LOGIN_DEFAULT_KEY;
    	if(null!=loginName){
    		ret=loginName.getName();
		}
        return  ret;
    }
    
    
    
    public static Logger getAccessLog() {
        return ACCESS_LOG;
    }


    public static Logger getT0loanLog() {
        return T0LOAN_LOG;
    }

	public static Logger getSlloanLog() {
		return SLLOAN_LOG;
	}
    
	 public static String getLineInfo() {  
         StackTraceElement ste = new Throwable().getStackTrace()[2];  
         return String.valueOf(ste.getLineNumber());  
  }  
    
}
